package com.woniu.secondhand.controller;

import com.alipay.api.internal.util.AlipaySignature;
import com.woniu.common.annotation.LoginUser;
import com.woniu.common.constant.RedisKeyConstant;
import com.woniu.common.entity.Result;
import com.woniu.common.entity.ResultCode;
import com.woniu.pay.constant.AliPayInfoConstants;
import com.woniu.secondhand.constant.SecondhandMessageConstant;
import com.woniu.secondhand.constant.SecondhandOrderConstant;
import com.woniu.secondhand.entity.dto.AfterOrderUpdateDTO;
import com.woniu.secondhand.entity.dto.BeforeOrderUpdateDTO;
import com.woniu.secondhand.entity.dto.MessageAddDTO;
import com.woniu.secondhand.pojo.SecondhandOrder;
import com.woniu.secondhand.service.ISecondhandMessageService;
import com.woniu.secondhand.service.ISecondhandOrderService;
import com.woniu.user.vo.UserLoginVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.*;

/**
 * <p>
 * 订单表 前端控制器
 * </p>
 *
 * @author HMMT
 * @since 2023-05-20
 */
@RestController
@RequestMapping("/secondhandOrder")
@Api(tags = "订单管理")
@Slf4j
public class SecondhandOrderController {

    @Autowired
    private ISecondhandOrderService orderService;
    @Autowired
    private ISecondhandMessageService messageService;
    @Autowired
    private RedisTemplate redisTemplate;

    @GetMapping("/create/token")
    @ApiOperation("0:创建接口幂等性校验token")
    private Result createToken() {
        String uuid = UUID.randomUUID().toString().replaceAll("-", "");
        redisTemplate.opsForValue().set(SecondhandOrderConstant.HEADER_TOKEN + uuid, uuid);
        return Result.ok(uuid);
    }

    @PostMapping("/create")
    @ApiOperation("1:创建订单")
    public Result createOrder(Integer productId, Integer addressId, @LoginUser UserLoginVO userLoginVO, HttpServletRequest request) {
        //0.判断是否重复提交
        String repeatToken = request.getHeader(SecondhandOrderConstant.HEADER_TOKEN_NAME);
        boolean flag = redisTemplate.delete(SecondhandOrderConstant.HEADER_TOKEN + repeatToken);
        if (!flag) {
            return Result.error(ResultCode.REPEAT_REQUEST.getCode(), ResultCode.REPEAT_REQUEST.getMessage());
        }
        SecondhandOrder order = orderService.createOrder(productId, addressId, userLoginVO);
        return Result.ok(order);
    }

    @PutMapping("/update/beforePay")
    @ApiOperation("2:在支付前更改订单")
    public Result<SecondhandOrder> updateOrderBeforePay(@RequestBody BeforeOrderUpdateDTO orderUpdateDTO) {
        SecondhandOrder order = orderService.updateOrderBeforePay(orderUpdateDTO);
        return Result.ok(order);
    }

    @PutMapping("/close/{orderId}")
    @ApiOperation("2.5:关闭订单")
    public Result<SecondhandOrder> closeOrder(@PathVariable Integer orderId, @LoginUser UserLoginVO userLoginVO) {
        orderService.closeOrder(orderId, userLoginVO);
        return Result.ok();
    }

    @PostMapping("/pay")
    @ApiOperation("3.付款")
    public Result pay(@RequestBody SecondhandOrder order) {
        orderService.pay(order);
        return Result.ok();
    }

    @PostMapping("/notify_url/test/{outTradeNo}")
    @ApiOperation("4:支付异步回调方法测试用")
    @SneakyThrows
    public String testNotifyUrl(@PathVariable String outTradeNo) {
        SecondhandOrder order = orderService.getByOrderNo(outTradeNo);
        if (order.getStatus() != 0) {
            log.debug("重复订单直接成功");
            return "success";
        }
        order.setStatus(SecondhandOrderConstant.BUY_SUCCESS);
        order.setPayType(SecondhandOrderConstant.ALI_PAY);
        order.setPaymentTime(new Date());
        orderService.updateById(order);
        MessageAddDTO messageAddDTO = new MessageAddDTO();
        messageAddDTO.setOrderId(order.getId());
        messageAddDTO.setMessageType(SecondhandMessageConstant.BUY_SUCCESS_MESSAGE);
        messageService.addBuySuccessMessage(messageAddDTO, order.getConsumerId());
        log.debug("order是{}", order);
        // 往支付表里添加一条信息
        redisTemplate.boundListOps(RedisKeyConstant.QUERY_ORDER_TRADE_NO).remove(1, outTradeNo);
        return "success";
    }

    @PutMapping("/update/afterPay")
    @ApiOperation("5.在支付后更改订单（添加物流信息）")
    public Result<SecondhandOrder> updateOrderAfterPay(@RequestBody AfterOrderUpdateDTO orderUpdateDTO, @LoginUser UserLoginVO userLoginVO) {
        SecondhandOrder order = orderService.updateOrderAfterPay(orderUpdateDTO, userLoginVO);
        return Result.ok(order);
    }

    @PutMapping("/update/confirm/{orderId}")
    @ApiOperation("6.主动确认收货")
    public Result<SecondhandOrder> updateOrderConfirm(@LoginUser UserLoginVO userLoginVO, @PathVariable Integer orderId) {
        SecondhandOrder order = orderService.updateOrderConfirm(userLoginVO, orderId);
        return Result.ok(order);
    }

    @PutMapping("/update/refund/{orderId}")
    @ApiOperation("7.退款")
    public Result<SecondhandOrder> updateOrderRefund(@LoginUser UserLoginVO userLoginVO, @PathVariable Integer orderId) {
        SecondhandOrder order = orderService.updateOrderRefund(userLoginVO, orderId);
        return Result.ok(order);
    }

    @PutMapping("/update")
    @ApiOperation("修改订单")
    public Result<SecondhandOrder> updateOrder(@RequestBody SecondhandOrder order) {
        boolean update = orderService.updateById(order);
        return Result.commonByFlag(update);
    }

    @GetMapping("/order_no/{orderNo}")
    @ApiOperation("根据orderNo来获取order对象")
    public Result<SecondhandOrder> getByOrderNo(@PathVariable("orderNo") String orderNo) {
        SecondhandOrder order = orderService.getByOrderNo(orderNo);
        return Result.ok(order);
    }

    @GetMapping("/productId/{productId}")
    @ApiOperation("根据productId来获取order对象")
    public Result<SecondhandOrder> getByProductIdAndStatusEqualsReceiveSuccess(@PathVariable("productId") Integer productId) {
        SecondhandOrder order = orderService.getByProductIdAndStatusEqualsReceiveSuccess(productId);
        return Result.ok(order);
    }

    @GetMapping("/return_url")
    @ApiOperation("支付同步回调方法")
    public String returnUrl() {
        log.debug("支付宝支付同步回调成功");
        return "redirect:https://www.baidu.com/";
    }

    @PostMapping("/notify_url")
    @ApiOperation("支付异步回调方法")
    @SneakyThrows
    public String notifyUrl(HttpServletRequest request) {
        //获取支付宝POST过来反馈信息
        Map<String, String> params = new HashMap<>();
        Map requestParams = request.getParameterMap();
        for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext(); ) {
            String name = (String) iter.next();
            String[] values = (String[]) requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i]
                        : valueStr + values[i] + ",";
            }
            //乱码解决，这段代码在出现乱码时使用。
            //valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
            params.put(name, valueStr);
        }
        //调用SDK验证签名
        boolean signVerified = AlipaySignature.rsaCheckV1(params, AliPayInfoConstants.ALIPAY_PUBLIC_KEY, AliPayInfoConstants.CHARSET, AliPayInfoConstants.SIGN_TYPE);
        if (!signVerified) {
            //  验签成功后，按照支付结果异步通知中的描述，对支付结果中的业务内容进行二次校验，校验成功后在response中返回success并继续商家自身业务处理，校验失败返回failure
            log.debug("验签失败");
            return "failure";
        }
        String out_trade_no = params.get("out_trade_no");
        SecondhandOrder order = orderService.getByOrderNo(out_trade_no);
        if (order.getStatus() != 0) {
            log.debug("重复订单直接成功");
            return "success";
        }
        order.setStatus(SecondhandOrderConstant.BUY_SUCCESS);
        order.setPayAmount(new BigDecimal(params.get("total_amount")));
        order.setPayType(SecondhandOrderConstant.ALI_PAY);
        order.setPaymentTime(new Date());
        orderService.updateById(order);
        MessageAddDTO messageAddDTO = new MessageAddDTO();
        messageAddDTO.setOrderId(order.getId());
        messageAddDTO.setMessageType(SecondhandMessageConstant.BUY_SUCCESS_MESSAGE);
        messageService.addBuySuccessMessage(messageAddDTO, order.getConsumerId());
        log.debug("order是{}", order);
        // 往支付表里添加一条信息
        redisTemplate.boundListOps(RedisKeyConstant.QUERY_ORDER_TRADE_NO).remove(1, out_trade_no);
        return "success";
    }
}
